package cn.tedu.mall.admin.service.impl;

import cn.tedu.mall.admin.ex.ServiceException;
import cn.tedu.mall.admin.mapper.AdminMapper;
import cn.tedu.mall.admin.mapper.AdminRoleMapper;
import cn.tedu.mall.admin.pojo.dto.AdminAddNewDTO;
import cn.tedu.mall.admin.pojo.dto.AdminLoginDTO;
import cn.tedu.mall.admin.pojo.entity.Admin;
import cn.tedu.mall.admin.pojo.vo.AdminListItemVO;
import cn.tedu.mall.admin.pojo.vo.AdminSimpleVO;
import cn.tedu.mall.admin.security.AdminDetails;
import cn.tedu.mall.admin.service.IAdminService;
import cn.tedu.mall.admin.util.JwtUtils;
import cn.tedu.mall.admin.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private AdminRoleMapper adminRoleMapper;

    @Override
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        String username = adminAddNewDTO.getUsername();
        int count = adminMapper.countByUsername(username);
        if (count > 1) {
            String message = "该用户已经存在";
            log.error(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        Admin admin = new Admin();
        BeanUtils.copyProperties(adminAddNewDTO, admin);
        admin.setLoginCount(0);
        admin.setLastLoginIp(null);
        admin.setGmtLastLogin(null);
        //Security开始
        String password = admin.getPassword();
        String encodePassword = passwordEncoder.encode(password);
        admin.setPassword(encodePassword);

        int insert = adminMapper.insert(admin);
        if (insert != 1) {
            String message = "添加失败，请联系管理员";
            log.error(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
    }

    @Override
    public void deleteById(Long id) {
        AdminSimpleVO simpleById = adminMapper.getSimpleById(id);
        if (simpleById == null) {
            String message = "删除管理员失败，尝试删除的数据不存在！";
            log.error(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        int rows = adminMapper.deleteById(id);
        if (rows != 1) {
            String message = "删除管理员失败，服务器忙，请稍后再次尝试！";
            log.error(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }
    }

    @Override
    public String login(AdminLoginDTO adminLoginDTO) {
        Authentication authentication = new UsernamePasswordAuthenticationToken(adminLoginDTO.getUsername(), adminLoginDTO.getPassword());
        Authentication loginResult = authenticationManager.authenticate(authentication);

        // 以上调用的authenticate()方法是会抛出异常的方法，如果还能执行到此处，则表示用户名与密码是匹配的
        log.debug("登录成功！认证方法返回的数据类型：{}", loginResult.getClass().getName());
        log.debug("登录成功！认证方法返回的数据：{}", loginResult);
        // 从认证结果中获取Principal，本质上是User类型，且是UserDetailsService中loadUserByUsername()返回的结果
        log.debug("认认信息中的Principal类型：{}", loginResult.getPrincipal().getClass().getName());
        log.debug("认认信息中的Principal数据：{}", loginResult.getPrincipal());
        AdminDetails adminDetails = (AdminDetails) loginResult.getPrincipal();
        Long id = adminDetails.getId();
        log.debug("登录成功的管理员id：{}", id);
        String username = adminDetails.getUsername();
        log.debug("登录成功的管理员用户名：{}", username);
        Collection<GrantedAuthority> authorities = adminDetails.getAuthorities();
        log.debug("登录成功的管理员权限：{}", authorities);
        String authoritiesString = JSON.toJSONString(authorities);
        log.debug("将管理员权限转换为JSON：{}", authoritiesString);

        Map<String,Object> claims = new HashMap<>();
        claims.put("id",adminDetails.getId());
        claims.put("username",adminDetails.getUsername());
        claims.put("authorities", authoritiesString);
        String jwt = JwtUtils.generate(claims);
        log.debug("{}",jwt);
        return jwt;
    }

    @Override
    public List<AdminListItemVO> list() {
        return adminMapper.list();
    }
}
